package com.anzhixin.action;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.swing.JOptionPane;
import javax.swing.JProgressBar;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.anzhixin.ui.MainFrame;
import com.anzhixin.util.FileUtil;

public class DownLoadActionListener implements ActionListener {
	private MainFrame frame;

	public DownLoadActionListener(MainFrame frame) {
		this.frame = frame;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		frame.getBtnDown().setEnabled(false);
		frame.setOperState(1);

		// 为了进度条不随窗口长时间任务运行而假死
		new Thread() {
			private Map<String,String> mapFiles = new HashMap<String, String>();
			private long downloadedSize=0; 
			private long fileSize=0;
			public void run() {
				// download xml
				SAXReader reader = new SAXReader();
				frame.getLblStatus().setText("正在连接服务器......");
				frame.getTxtLog().insert("\n正在连接服务器......", 0);
				URL url = null;
				try {
					url = new URL("http://www.anzhixin.com/soft/softMeta.xml");
				} catch (MalformedURLException e) {
					e.printStackTrace();
				}
				int handleStep = 0;
				String fileDir = System.getProperty("user.dir");
				String localDir = "";
				try {
					Document document = reader.read(url);
					// parse xml
					Element root = document.getRootElement();
					frame.getLblStatus().setText("已成功连接到服务器。");

					frame.getTxtLog().insert("\n已成功连接到服务器。", 0);
					frame.getProgressBarAll().setValue(10);
					for (Iterator i = root.elementIterator(); i.hasNext();) {
						Element elementSoft = (Element) i.next();
						String softSid = elementSoft.attributeValue("sid");
						if (softSid != null && softSid.equals(frame.getSoftSid())) {
							// / found
							String softVersion = elementSoft.attributeValue("version");
							localDir = elementSoft.attributeValue("localDir");
							handleStep++;
							if (softVersion != null && !softVersion.equals(frame.getSoftVersion())) {
								// to download
								// download files
								handleStep++;
								frame.getLblStatus().setText("检测到新版本：" + softVersion + "。");
								frame.getTxtLog().insert("\n检测到新版本：" + softVersion + "。正在获取文件列表......", 0);
								frame.getProgressBarAll().setValue(20);
								frame.setOperState(2);
								//第一次循环，获取文件数量和文件总大小
								int fileCount = 0;
								for (Iterator it = elementSoft.elementIterator(); it.hasNext();) {
									Element elementUrl = (Element) it.next();
//									System.out.println(elementUrl.getText());
//									System.out.println(elementUrl.attributeValue("localDir"));
									String fileUrl = elementUrl.getText();
									if(fileUrl!=null&&!"".equals(fileUrl)){
										long fileSizeCurr=0;
										try {
											fileSizeCurr = getFileSize(fileUrl);
										} catch (IOException e) {
											e.printStackTrace();
											frame.getTxtLog().insert("\n无法成功获取某文件大小。原因："+e.getLocalizedMessage(), 0);
										}
										fileSize += fileSizeCurr;
										fileCount++;
										mapFiles.put(fileUrl, String.valueOf(fileSizeCurr));
									}
								}
								frame.getTxtLog().insert("\n文件数量：" + fileCount + "，总大小：" + fileSize, 0);
								frame.getProgressBarAll().setValue(30);
								//第二次循环开始下载
								for (Iterator it = elementSoft.elementIterator(); it.hasNext();) {
									Element elementUrl = (Element) it.next();
//									System.out.println(elementUrl.getText());
//									System.out.println(elementUrl.attributeValue("localDir"));
									String fileUrl = elementUrl.getText();
									if(fileUrl!=null&&!"".equals(fileUrl)){
										String fileName = fileUrl.substring(fileUrl.lastIndexOf("/")+1);
										frame.getLblStatus().setText("下载‘"+fileName+"’中，请稍候......");
										frame.getTxtLog().insert("\n开始下载"+fileName+"，文件大小"+mapFiles.get(fileUrl), 0);
										try {
											String tempDir = fileDir+"/update_files";
											File f = new File(tempDir);
											if(f.exists()&&f.isDirectory()){
												f.delete();
												f.mkdir();
											}else{
												f.mkdir();
											}
//											if(tempDir)
											frame.getProgressBarCurr().setValue(0);
											//frame.getProgressBarCurr().setString("当前下载" + fileName);
											downloadFile(fileUrl, FileUtil.getRelativePath(tempDir, elementUrl.attributeValue("tempDir"))+"/"+ fileName,frame.getProgressBarCurr(),frame.getProgressBarAll());
											frame.getTxtLog().insert("\n"+fileName+"下载完成！", 0);
										} catch (IOException e) {
											e.printStackTrace();
											handleStep++;
											frame.getTxtLog().insert("\n" + fileName + "下载失败。原因：" + e.getLocalizedMessage(), 0);
											break;
										}
									}
								}

							}
							break;
						}
					}
					
					frame.getProgressBarAll().setValue(155);
					switch (handleStep) {
					case 0:
						frame.getLblStatus().setText("未找到该软件的升级信息。");
						break;
					case 1:
						frame.getLblStatus().setText("您使用的就是最新版本，无需升级。");
						break;
					case 2:
						frame.getLblStatus().setText("成功下载完升级文件。");
						frame.getProgressBarAll().setValue(150);
						break;
					case 3:
						frame.getLblStatus().setText("升级文件下载失败，请稍候重试。");
						break;
					default:
						break;
					}
					frame.getTxtLog().insert("\n"+frame.getLblStatus().getText(), 0);
					
					
				} catch (DocumentException e) {
					e.printStackTrace();
					frame.getLblStatus().setText("获取服务器版本信息失败。");
					frame.getTxtLog().insert("\n"+frame.getLblStatus().getText(), 0);
				}
				if(handleStep==2){
					frame.getTxtLog().insert("\n正在复制并更新到新版本......", 0);
					frame.getLblStatus().setText("更新文件中.....");
					String fileApp  = FileUtil.getRelativePath(fileDir, localDir);
					int done=0;
					while(done==0){
						int retCode=new FileUtil().fileCopy(fileDir+"/update_files", fileApp);
						
						if(retCode==0){
							done=1;
						}else{
							if(JOptionPane.NO_OPTION==JOptionPane.showConfirmDialog(frame, "文件复制过程中出错，请关闭相关正在运行的 主程序 后重试！\n点‘是’重试，点‘否’您可能下次需要重新升级！", "重试？", JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE)){
								done=2;
							}else{
								
							}
						}
					}
					if(done==1){
						frame.getTxtLog().insert("\n升级完成！", 0);
						frame.getLblStatus().setText("升级完成！");
					}else{
						frame.getTxtLog().insert("\n升级未完成！您需要下次再次升级！", 0);
						frame.getLblStatus().setText("升级未完成！您需要下次再次升级");
					}
					frame.getProgressBarAll().setValue(155);
				}
				frame.setOperState(0);
				frame.getBtnDown().setEnabled(true);
			}
			/** 下载指定url的文件 
			 * @throws IOException */
			private void downloadFile(String sURL,String storeFullPathFileName,JProgressBar barCurr, JProgressBar barTotal) throws IOException {
				// String sURL = "http://www.anzhixin.com/soft/download/ms_update.rar";
				long nStartPos = 0;
				int nRead = 0;
				URL url = new URL(sURL);
				// 打开连接
				HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
				// 获得文件长度
				long nEndPos = Long.parseLong(mapFiles.get(sURL));
//				File file = new File(storeFullPathFileName);
//				if(!file.exists()){
//					file.createNewFile();
//				}
				RandomAccessFile oSavedFile = new RandomAccessFile(storeFullPathFileName, "rw");
				httpConnection.setRequestProperty("User-Agent", "Internet Explorer");
				String sProperty = "bytes=" + nStartPos + "-";
				// 告诉服务器这个文件从nStartPos字节开始传
				httpConnection.setRequestProperty("RANGE", sProperty);
//				System.out.println(sProperty);
				
				//barTotal.setString("总进度");
				InputStream input = httpConnection.getInputStream();
				byte[] b = new byte[1024];
				// 读取网络文件,写入指定的文件中
				while ((nRead = input.read(b, 0, 1024)) > 0 && nStartPos < nEndPos) {
					oSavedFile.write(b, 0, nRead);
					nStartPos += nRead;
					downloadedSize+=nRead;
					int intPercent = Integer.parseInt(String.valueOf(100*nStartPos/nEndPos));
//					System.out.println(intPercent);
					if(barCurr!=null){
						barCurr.setValue(intPercent);
					}
					if(barTotal!=null){
						barTotal.setValue(Integer.parseInt(String.valueOf(30+100*downloadedSize/fileSize)));
					}
				}
				httpConnection.disconnect();
//				try {
//				} catch (Exception e) {
//					e.printStackTrace();
//				}
			}
			
			/** 获得文件长度 
			 * @throws IOException */
			private long getFileSize(String sURL) throws IOException {
				int nFileLength = -1;
				URL url = new URL(sURL);
				HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
				httpConnection.setRequestProperty("User-Agent", "Internet Explorer");
				int responseCode = httpConnection.getResponseCode();
				if (responseCode >= 400) {
					System.err.println("Error Code : " + responseCode);
					return -2; // -2 represent access is error
				}
				String sHeader;
				for (int i = 1;; i++) {
					sHeader = httpConnection.getHeaderFieldKey(i);
					if (sHeader != null) {
						if (sHeader.equals("Content-Length")) {
							nFileLength = Integer.parseInt(httpConnection.getHeaderField(sHeader));
							break;
						}
					} else
						break;
				}
				
				return nFileLength;
			}
		}.start();
	}

}
